/*
 *  ckr_spec_less_than_comparison.cpp
 *  ckrSpec
 *
 *  Created by C. Keith Ray on 2006.11.05.
 *  Copyright 2006 __MyCompanyName__. All rights reserved.
 *
 */

#import "ckr_spec_cpp_specs.h"
#import "ckr_spec_cpp.h"

#include <iostream>
#include <sstream>
#include <vector>
#include <deque>

#include <assert.h>

using namespace std;
using namespace ckr;

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

static void integral_values_less_than_in_should_be_less_than_reports_nothing();
static void integral_values_not_less_than_in_should_be_less_than_reports_failure();

static void c_string_values_not_less_than_in_should_be_less_than_reports_failure();
static void c_string_values_less_than_in_should_be_less_than_reports_nothing();
static void c_strings_less_than_null_report_failure();

static void std_string_values_less_than_in_should_be_less_than_reports_nothing();
static void std_string_values_not_less_than_in_should_be_less_than_should_report_failure();

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void run_less_than_comparison_specs()
{
	integral_values_less_than_in_should_be_less_than_reports_nothing();
	integral_values_not_less_than_in_should_be_less_than_reports_failure();

	c_string_values_not_less_than_in_should_be_less_than_reports_failure();
	c_string_values_less_than_in_should_be_less_than_reports_nothing();
	c_strings_less_than_null_report_failure();

	std_string_values_less_than_in_should_be_less_than_reports_nothing();
	std_string_values_not_less_than_in_should_be_less_than_should_report_failure();
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(Integral_values_less_than_in_should_be_less_than_context);

void Integral_values_less_than_in_should_be_less_than_context::spec()
{
	int int98 = 98;
	int int99 = 99;

	VALUE( int98 ).SHOULD_BE_LESS_THAN( int99 ); // no msg expected
}

static void integral_values_less_than_in_should_be_less_than_reports_nothing()
{
	Integral_values_less_than_in_should_be_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	std::string expected; // empty string

	assert( expected == actual );
}

// I had to trim off line numbers from my assertion strings because they changed when I added new code at the top of this file.
// Regular expression matching would be good here, but I want to only depend on STL and the rest of the standard C++ library, not
// boost or other class libraries, even though boost has a nice regex library.

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

// next to do... greater_than, less_than, etc.

DECLARE_SPEC(Integral_values_not_less_than_in_should_be_less_than_context);

void Integral_values_not_less_than_in_should_be_less_than_context::spec()
{
	int int98 = 98;
	int int99 = 99;
	int intAlso99 = 99;

	VALUE( int99 ).SHOULD_BE_LESS_THAN( int98 ); // failure msg expected
	VALUE( intAlso99 ).SHOULD_BE_LESS_THAN( int99 ); // failure msg expected		
}

static void integral_values_not_less_than_in_should_be_less_than_reports_failure()
{
	Integral_values_not_less_than_in_should_be_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	{
		std::string expected1( "int99 (99) should be less than int98 (98) FAILED in Integral_values_not_less_than_in_should_be_less_than_context; line " );
		std::string::size_type foundPos1 = actual.find( expected1, 0 );
		assert( foundPos1 != std::string::npos );
	}
	{
		std::string expected2( "intAlso99 (99) should be less than int99 (99) FAILED in Integral_values_not_less_than_in_should_be_less_than_context; line " );
		std::string::size_type foundPos2 = actual.find( expected2, 0 );
		assert( foundPos2 != std::string::npos );
	}
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(C_strings_not_less_than_in_less_than_context);

void C_strings_not_less_than_in_less_than_context::spec()
{
	char number99[] = "Number99";
	char smart[] = "Smart";
	char* alsoSmart = "Smart";

	CSTRING_VALUE( smart ).SHOULD_BE_LESS_THAN( number99 ); // failure msg expected
	CSTRING_VALUE( alsoSmart ).SHOULD_BE_LESS_THAN( smart ); // failure msg expected		
}

static void c_string_values_not_less_than_in_should_be_less_than_reports_failure()
{
	C_strings_not_less_than_in_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	{
		std::string expected1( "smart (Smart) should be less than number99 (Number99) FAILED in C_strings_not_less_than_in_less_than_context; line " );
		std::string::size_type foundPos1 = actual.find( expected1, 0 );
		assert( foundPos1 != std::string::npos );
	}
	{
		std::string expected2( "alsoSmart (Smart) should be less than smart (Smart) FAILED in C_strings_not_less_than_in_less_than_context; line " );
		std::string::size_type foundPos2 = actual.find( expected2, 0 );
		assert( foundPos2 != std::string::npos );
	}
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(C_strings_less_than_in_less_than_context);

void C_strings_less_than_in_less_than_context::spec()
{
	char number99[] = "Number99";
	char smart[] = "Smart";

	CSTRING_VALUE( number99 ).SHOULD_BE_LESS_THAN( smart ); // no msg expected
}

static void c_string_values_less_than_in_should_be_less_than_reports_nothing()
{
	C_strings_less_than_in_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	std::string expected;//empty string

	assert( expected == actual );
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(C_string_null_less_thancontext);

void C_string_null_less_thancontext::spec()
{
	char* nullPtr = 0;

	CSTRING_VALUE( "Frank" ).SHOULD_BE_LESS_THAN( nullPtr ); // failure msg expected
	CSTRING_VALUE( nullPtr ).SHOULD_BE_LESS_THAN( "Mary" ); // failure msg expected
	CSTRING_VALUE( nullPtr ).SHOULD_BE_LESS_THAN( nullPtr ); // failure msg expected
}


static void c_strings_less_than_null_report_failure()
{
	C_string_null_less_thancontext aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	{
		std::string expected1( "\"Frank\" (Frank) should be less than nullPtr ((NULL POINTER)) FAILED in C_string_null_less_thancontext; line ");
		std::string::size_type foundPos1 = actual.find( expected1, 0 );

		assert( foundPos1 != std::string::npos );
	}
	{
		std::string expected2( "nullPtr ((NULL POINTER)) should be less than \"Mary\" (Mary) FAILED in C_string_null_less_thancontext; line ");
		std::string::size_type foundPos2 = actual.find( expected2, 0 );

		assert( foundPos2 != std::string::npos );
	}
	{
		std::string expected2( "nullPtr ((NULL POINTER)) should be less than nullPtr ((NULL POINTER)) FAILED in C_string_null_less_thancontext; line ");
		std::string::size_type foundPos2 = actual.find( expected2, 0 );

		assert( foundPos2 != std::string::npos );
	}
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(Std_string_values_less_than_in_should_be_less_than_context);

void Std_string_values_less_than_in_should_be_less_than_context::spec()
{
	std::string number99 = "Number99";
	std::string smart = "Smart";

	VALUE( number99 ).SHOULD_BE_LESS_THAN( smart ); // no msg expected
}

static void std_string_values_less_than_in_should_be_less_than_reports_nothing()
{
	Std_string_values_less_than_in_should_be_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	std::string expected; // empty string

	assert( expected == actual );
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DECLARE_SPEC(Std_string_values_not_less_than_in_should_be_less_than_context);

void Std_string_values_not_less_than_in_should_be_less_than_context::spec()
{
	std::string number99 = "Number99";
	std::string smart = "Smart";
	std::string alsoSmart = "Smart";

	VALUE( smart ).SHOULD_BE_LESS_THAN( number99 ); // failure msg expected
	VALUE( alsoSmart ).SHOULD_BE_LESS_THAN( smart ); // failure msg expected		
}

static void std_string_values_not_less_than_in_should_be_less_than_should_report_failure()
{
	Std_string_values_not_less_than_in_should_be_less_than_context aContext;

	RecordingFailuresSpecListener listener;
	aContext.run_spec( & listener );
	std::string actual = listener.logStr();

	{
		std::string expected1( "smart (Smart) should be less than number99 (Number99) FAILED in Std_string_values_not_less_than_in_should_be_less_than_context; line " );
		std::string::size_type foundPos1 = actual.find( expected1, 0 );
		assert( foundPos1 != std::string::npos );
	}
	{
		std::string expected2( "alsoSmart (Smart) should be less than smart (Smart) FAILED in Std_string_values_not_less_than_in_should_be_less_than_context; line " );
		std::string::size_type foundPos2 = actual.find( expected2, 0 );
		assert( foundPos2 != std::string::npos );
	}
}

//  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
